package mrusanov.tournament

import mrusanov.team.{Team, Club}
import util.Random
import java.util.Date

class KnockOutTournamentRound(clubsCount:Int, rounds:Int, dates:Vector[Date],
      reward:KnockOutRoundTournamentReward = new KnockOutRoundTournamentReward(0, 0),
      pairWinner:(List[MatchInfo] => Team) = (ls) => ls(0).winner)

  extends TournamentRound(clubsCount, reward){
  require(dates.size == rounds, "Dates count and matches count are different")

  override def initMatches() {
    var matchesRound = List[MatchInfo]()

    for (i <- 0 until rounds) {
       matchesRound = if (i == 0) getMatches(teams, dates(0))
                      else reverseSides(matchesRound, dates(i))
      _matches += (i -> matchesRound)
    }
  }

  private def reverseSides(list:List[MatchInfo], date:Date) : List[MatchInfo] = {
     for (m <- list) yield new MatchInfo(m.guest, m.host, date)
  }

  override def passedRound:List[Team] = {
    if (!isOver) {
      return List()
    }

    val groupedPairs = groupMatchesByPairs()
    (for (pair <- groupedPairs) yield pairWinner(pair._2)).toList

  }

  override def resultsForReward:List[Team] = {
    val winners = passedRound
    val losers = teams filterNot( c => winners.contains(c))
    winners ::: losers
  }

  def groupMatchesByPairs():Map[(Team, Team), List[MatchInfo]] = {
    var map = Map[(Team, Team), List[MatchInfo]]()
    val allMatches = matches.foldLeft(List[MatchInfo]())((acc,kv) => kv._2 ::: acc)
    allMatches foreach(m => {
        if (map.contains((m.host, m.guest))) {
          val list = m :: map((m.host, m.guest))
          map += (m.host, m.guest) -> list
        } else if (map.contains((m.guest, m.host))) {
          val list = m :: map((m.guest, m.host))
          map += (m.guest, m.host) -> list
        } else {
          val list = m :: Nil
          map += (m.guest, m.host) -> list
        }
      }
    )

    map
  }
}
